home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / Sample Code / Devices / RAMDisk 1.4d5 / RamINIT.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-07  |  13.9 KB  |  499 lines  |  [TEXT/CWIE]

  1. #define __DebugVersion    1
  2. /*
  3. **    Apple Macintosh Developer Technical Support
  4. **
  5. **    RAMInit.c: An INIT which installs DRVR for RamDisk
  6. **
  7. **    by Gordon Sheridan and Jim Luther
  8. **  modified incessantly by Brian Bechtel
  9. **  and even more so by Quinn "The Eskimo!"
  10. **
  11. **    File:        RamINIT.c
  12. **
  13. **    Copyright © 1992-1996 Apple Computer, Inc.
  14. **    All rights reserved.
  15. **
  16. **    You may incorporate this sample code into your applications without
  17. **    restriction, though the sample code has been provided "AS IS" and the
  18. **    responsibility for its operation is 100% yours.  However, what you are
  19. **    not permitted to do is to redistribute the source as "DTS Sample Code"
  20. **    after having made changes. If you're going to re-distribute the source,
  21. **    we require that you make it clear in the source that the code was
  22. **    descended from Apple Sample Code, but that you've made changes.
  23. **
  24. **    Change History (most recent first):
  25. **
  26. **         <1.4>    19970207      Quinn    Reworked to use new file layout and bring generally
  27. **                                    up-to-date.
  28. **        <1.4>    19970207    Quinn    Rewrote to use TradDriverLoaderLib
  29. **                                    Junked some unused prototypes
  30. **                                    Renamed RemoveDrive to RemoveDriveFromQueue
  31. **        <1.3>    08/23/96    BL°B    Change dcePtr to dceHandle. Thanks to
  32. **                                    Tim Fredenburg for pointing out the error.
  33. **        <1.3>    06/20/96    BL°B    Changes to new routine names
  34. **        <1.2>    07/03/95    BL°B    Many changes for Universal Header 2.0 
  35. **                                    compliance.  Changed how we install driver.
  36. **                                    Other bug fixes. See "Changes in 1.2" for
  37. **                                    details.
  38. **         <7>    06/10/94    BL°B    Explicitly set zone to system zone before
  39. **                                    getting the DRVR resource.  Symantec 7.0
  40. **                                    doesn't set the System attribute on the DRVR
  41. **                                    resource.  This can be hard to track down.
  42. **         <6>    05/19/94    BL°B    Modified debugger macros to avoid use of ANSI
  43. **                                     routines, and weird c-string dependencies.
  44. **         <5>    10/15/93    JML        Added code to resize unit table if needed.
  45. **         <4>    10/14/93    JML        Implement AddDebuggerLabels routine for MacsBug.
  46. **                                     Added Panic debug macros.
  47. **         <3>     6/29/93    gs        Change AddDriveToQueue to start with drive number 5.
  48. **         <2>     6/28/93    gs        Change _DebugVersion to __DebugVersion
  49. **         <1>     6/13/93    gs        Implement AddDebuggerLabels routine for TMON.
  50. **         <0>     4/17/92    gs        Clean up for Sample Code release.
  51. **/
  52.  
  53. #ifdef __MWERKS__
  54. #include <A4Stuff.h>
  55. #endif
  56. #ifdef THINK_C
  57. #include <SetupA4.h>
  58. #endif
  59.  
  60. #include <string.h>
  61. #include <TextUtils.h>
  62. #include <QuickDraw.h>
  63. #include <Traps.h>
  64. #include <Gestalt.h>
  65. #include <Memory.h>
  66. #include <Resources.h>
  67. #include <DiskInit.h>
  68.  
  69. #include "RamDiskCommon.h"
  70. #include "TradDriverLoaderLib.h"
  71. #include "ShowInitIcon.h"
  72.  
  73. ///////////////////////////////////////////////////////////////////////////
  74.  
  75. #define        kDriverName        "\p.RamDRVR"
  76.  
  77. enum {
  78.     kMinUnitNum = 48        /* the lowest unit number we can use */
  79. };
  80.  
  81. ///////////////////////////////////////////////////////////////////////////
  82. //
  83. // Custom drive queue element.  Normally you might to extend this to have
  84. // extra drive-specific variables, but in this case we have no extra
  85. // variables.  Still, we define our own structure rather than use
  86. // the one in <Files.h> because our structure has the magic "flags"
  87. // field at the front.
  88.  
  89. struct MyDrvQEl
  90. {
  91.     long            flags;
  92.     QElemPtr        qLink;
  93.     short            qType;
  94.     short            dQDrive;
  95.     short            dQRefNum;
  96.     short            dQFSID;
  97.     unsigned short    dQDrvSz;
  98.     unsigned short    dQDrvSz2;
  99. };
  100. typedef struct MyDrvQEl MyDrvQEl;
  101. typedef MyDrvQEl *MyDrvQElPtr;
  102.  
  103. ///////////////////////////////////////////////////////////////////////////
  104.  
  105. enum {
  106.     // ICN#
  107.     rLoadOKIcon        =    -4064,    /* same as cdev icon */
  108.     rLoadBadIcon    =    -4033,
  109.     rPhysicalIcon    =    -4034,
  110.     rMediaIcon        =    -4035
  111. };
  112.  
  113. ///////////////////////////////////////////////////////////////////////////
  114.  
  115. static OSErr InitializeGlobals (DrvrGlobals *driverGlobals)
  116.     // Initialize the globals using data read from resources.
  117. {
  118.     OSErr            result = -1;
  119.     Handle            physicalIconHandle;
  120.     Handle            mediaIconHandle;
  121.     VersRecHndl        versionHandle;
  122.     ConfigRecHandle    configHandle;
  123.     long            length;
  124.  
  125.     driverGlobals->ramDisk = nil;    /* RAM disk memory isn't allocated yet */
  126.  
  127.     /* Get the user configuration, icons, and the "where" string */
  128.     configHandle = (ConfigRecHandle)Get1Resource ('RDcf', rConfiguration);
  129.     physicalIconHandle = Get1Resource('ICN#', rPhysicalIcon);
  130.     mediaIconHandle = Get1Resource('ICN#', rMediaIcon);
  131.     
  132.     versionHandle = (VersRecHndl) Get1Resource('vers', 1);
  133.     
  134.     if (configHandle && physicalIconHandle && mediaIconHandle && versionHandle)
  135.     {
  136.         /* See if we are supposed to install */
  137.         if ((**configHandle).install)
  138.         {            
  139.             /* Copy the user's preferred volume name to the driver globals. */
  140.             length = (**configHandle).volumeName[0]+1;
  141.             BlockMoveData((**configHandle).volumeName, driverGlobals->volumeName, length);
  142.             
  143.             /* Copy ICN# to driver globals so it has a physical location icon for volumes. */
  144.             BlockMoveData( &(**physicalIconHandle), (Ptr)(driverGlobals->physicalIcon), kLargeIconSize);
  145.             
  146.             /* Copy ICN# to driver globals so it has a default media icon for volumes. */
  147.             BlockMoveData( &(**mediaIconHandle), (Ptr)(driverGlobals->mediaIcon), kLargeIconSize);
  148.             
  149.             /* Put the drive location string into the driver globals. */
  150.             GetIndString(driverGlobals->locationStr, rStringList, strLocationStr);
  151.             if (ResError() != noErr)
  152.                 BlockMoveData("\pIn RAM", driverGlobals->locationStr, 7);
  153.                         
  154.             driverGlobals->ramSize = (**configHandle).size * 1024;
  155.             
  156.             driverGlobals->driverVersion = (**versionHandle).numericVersion;
  157.             
  158.             result = noErr;
  159.         }
  160.     }
  161.     
  162.     if (configHandle)
  163.         ReleaseResource((Handle)configHandle);
  164.     else
  165.         Panic("\pYou forgot to turn settings on in control panel");
  166.     if (physicalIconHandle)
  167.         ReleaseResource(physicalIconHandle);
  168.     if (mediaIconHandle)
  169.         ReleaseResource(mediaIconHandle);
  170.     
  171.     return (result);
  172. }
  173.  
  174. ///////////////////////////////////////////////////////////////////////////
  175.  
  176. static OSErr AddDriveToQueue (long size, short drvrRef, short *driveNum)
  177.     // Find the first unused drive number greater than 4, allocate and initialize
  178.     // a drive queue element (including the drive flags), and add the drive queue
  179.     // element to the drive queue.
  180. {
  181.     OSErr        result = noErr;
  182.     QHdrPtr        driveQHdr;
  183.     DrvQEl        *drivePtr;
  184.     MyDrvQElPtr    newDrivePtr;
  185.     Boolean        driveNumFound = false;
  186.  
  187.     
  188.     driveQHdr = GetDrvQHdr();
  189.     
  190.     /* find first free drive number */
  191.     *driveNum = 5;                                            /* drive numbers 1-4 are reserved */
  192.     while (! driveNumFound)
  193.     {
  194.         drivePtr = (DrvQEl *)driveQHdr->qHead;                /* get first drive */
  195.         while (drivePtr && *driveNum != drivePtr->dQDrive)    /* order of tests important! */
  196.             drivePtr = (DrvQEl *)drivePtr->qLink;            /* get next drive */
  197.         
  198.         if (drivePtr == nil)
  199.             driveNumFound = true;
  200.         else
  201.             ++(*driveNum);
  202.     }
  203.  
  204.     if (*driveNum > 0)    /* must be a positive short */
  205.     {
  206.         /* allocate new drive queue element */
  207.         newDrivePtr = (MyDrvQElPtr)NewPtrSysClear(sizeof(MyDrvQEl));            
  208.         if (newDrivePtr != nil)
  209.         {
  210.             newDrivePtr->flags        = 0x00080000;            /* non-ejectable, disk not locked */
  211.             newDrivePtr->qType        = 1;                    /* see IM vol.4 p.181 */
  212.             newDrivePtr->dQDrive    = *driveNum;            /* •• dQDrive and dQRefNum are filled */
  213.             newDrivePtr->dQRefNum    = drvrRef;                /* •• in by AddDrive */
  214.             newDrivePtr->dQFSID        = 0;                    /* HFS */
  215.             newDrivePtr->dQDrvSz    = size & 0x0000FFFF;    /* dQDrvSz  = LoWord of size */
  216.             newDrivePtr->dQDrvSz2    = size >> 16;            /* dQDrvSz2 = HiWord of size */
  217.             
  218.             AddDrive (drvrRef, *driveNum, (DrvQEl *)&newDrivePtr->qLink);
  219.         }
  220.         else
  221.             result = memFullErr;
  222.     }
  223.     else
  224.         /* more than 32768 drives!?! */
  225.         result = nsDrvErr;
  226.     
  227.     return (result);
  228. }
  229.  
  230. ///////////////////////////////////////////////////////////////////////////
  231.  
  232. static OSErr RemoveDriveFromQueue (short driveNum, DrvQElPtr *drivePtr)
  233.     // Find the drive queue element for driveNum in the drive queue and Dequeue it.
  234.     // Return pointer to the drive queue element removed in *drivePtr.
  235. {
  236.     QHdrPtr        driveQHdr;
  237.  
  238.     driveQHdr = GetDrvQHdr();
  239.     *drivePtr = (DrvQEl *)driveQHdr->qHead;                    /* get first drive */
  240.     while (*drivePtr && (driveNum != (*drivePtr)->dQDrive))    /* order of tests important! */
  241.         *drivePtr = (DrvQEl *)(*drivePtr)->qLink;            /* get next drive */
  242.     
  243.     if (*drivePtr != nil)
  244.         return (Dequeue((QElemPtr)*drivePtr, driveQHdr));
  245.     else
  246.         return (nsDrvErr);
  247. }
  248.  
  249. ///////////////////////////////////////////////////////////////////////////
  250.  
  251. static short NumToolboxTraps (void)
  252. {
  253.     if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap) )
  254.         return (0x200);
  255.     else
  256.         return (0x400);
  257. }
  258.  
  259. ///////////////////////////////////////////////////////////////////////////
  260.  
  261. static TrapType GetTrapType (short theTrap)
  262. {
  263.     if (theTrap & 0x0800)
  264.         return (ToolTrap);
  265.     else
  266.         return (OSTrap);
  267. }
  268.  
  269. ///////////////////////////////////////////////////////////////////////////
  270.  
  271. static Boolean TrapAvailable (short theTrap)
  272. {
  273.     TrapType    tType;
  274.     
  275.     tType = GetTrapType(theTrap);
  276.     if (tType == ToolTrap)
  277.     {
  278.         theTrap = theTrap & 0x7FF;
  279.         if (theTrap >= NumToolboxTraps() )
  280.             theTrap = _Unimplemented;
  281.     }
  282.     
  283.     return (NGetTrapAddress(theTrap, tType) !=
  284.             NGetTrapAddress(_Unimplemented, ToolTrap) );
  285. }
  286.  
  287. ///////////////////////////////////////////////////////////////////////////
  288.  
  289. #define kMacsbugMacroStr    "\p;MC RamDisk 'DM #"
  290. #define kMacsbugMacroStr2    "\p';g"
  291.  
  292. #define kTMONMacroStr        "\p™AddLabel RamDisk,."
  293. #define kTMONMacroStr2        "\p,."
  294.  
  295. #define AddString(src, dst) {    BlockMoveData(&src[1], dst+i, src[0]); i += src[0]; }
  296.  
  297. static void AddDebuggerLabels (DrvrGlobals driverGlobals)
  298.     // Add TMON or MacsBug debugger macros for easy viewing of RamDisk
  299. {
  300.     Str255        strbuf = "\p";
  301.     Str31        numstr;
  302.     long        tmonVal;
  303.     short        err;
  304.     Boolean     done = false;
  305.     SignedByte    debugFlags;
  306.     short        i;
  307.  
  308.     if (TrapAvailable(_Gestalt))    /* check for TMON */
  309.     {
  310.         err = Gestalt('TMON',&tmonVal);
  311.         if (err == 0)
  312.         {
  313.             /* Add TMON label */
  314.             i = 1;
  315.             AddString(kTMONMacroStr, strbuf);
  316.             NumToString((long)driverGlobals.ramDisk,numstr);
  317.             AddString(numstr, strbuf);
  318.             AddString(kTMONMacroStr2, strbuf);
  319.             NumToString(driverGlobals.ramSize,numstr);
  320.             AddString(numstr, strbuf);
  321.             strbuf[0] = i - 1;
  322.  
  323.             DebugStr(strbuf);
  324.             
  325.             done = true;
  326.         }
  327.     }
  328.     if (!done)    /* If TMON isn't installed, define a macro for MacsBug */
  329.     {
  330.         debugFlags = *(SignedByte *) 0x0BFF;        // MacJmpFlag
  331.         if (debugFlags == -1)
  332.             debugFlags = *(SignedByte *) 0x0120;    // MacJmp
  333.         
  334.         if (debugFlags & 0x20)
  335.         {
  336.             /* Define MacsBug macro */
  337.             i = 1;
  338.             
  339.             AddString(kMacsbugMacroStr, strbuf);
  340.             NumToString((long)driverGlobals.ramDisk, numstr);
  341.             AddString(numstr, strbuf);
  342.             AddString(kMacsbugMacroStr2, strbuf);
  343.             strbuf[0] = i - 1;
  344.             
  345.             DebugStr(strbuf);
  346.         }
  347.     }
  348. }
  349.  
  350. ///////////////////////////////////////////////////////////////////////////
  351.  
  352. void    main (void)
  353. {
  354.     DrvrGlobals    driverGlobals;
  355.     short        csParam[11];
  356.     short        drvrRefNum = 0;
  357.     short        driveNum = 0;
  358.     DrvQElPtr    driveQElPtr;
  359.     OSErr        result;
  360.     DCtlHandle    dceHandle;
  361.     Boolean        driverInstalled = false;
  362.  
  363.     #ifdef THINK_C
  364.         RememberA0();
  365.         SetUpA4();
  366.     #endif
  367.     #ifdef __MWERKS__
  368.         long oldA4 = SetCurrentA4();
  369.     #endif
  370.  
  371.     Panic("\pStarting RAMDisk");
  372.     ShowInitIcon(rLoadOKIcon,false);    /* show OK icon to indicate we're executing */
  373.     
  374.     result = InitializeGlobals(&driverGlobals);
  375.     if (result != noErr)
  376.     {
  377.         Panic("\pCould not initialize globals");
  378.         goto Done;
  379.     }
  380.  
  381.     driverGlobals.ramDisk = NewPtrSysClear(driverGlobals.ramSize);
  382.     if (driverGlobals.ramDisk == nil)
  383.     {
  384.         Panic("\pNewSysPtr = nil");
  385.         result = memFullErr;
  386.         goto Done;
  387.     }
  388.  
  389.     #if        __DebugVersion
  390.         AddDebuggerLabels(driverGlobals);
  391.     #endif    __DebugVersion
  392.     
  393.     // <1.4>
  394.     result = TradInstallDriverFromResource(0, kDriverName,
  395.             kMinUnitNum,
  396.             TradHighestUnitNumber() + 1,
  397.             &drvrRefNum);
  398.     if (result == noErr || result == dupFNErr) {
  399.         driverInstalled = (result == noErr);
  400.         result = TradOpenInstalledDriver(drvrRefNum, fsRdWrPerm);
  401.     } else {
  402.         Panic("\pTradInstallDriverFromResource failed!");
  403.         goto Done;
  404.     }
  405.  
  406.     if (result != noErr)
  407.     {
  408.         Panic("\pTradOpenInstalledDriver failed");
  409.         goto Done;
  410.     }
  411.     
  412.     /* put in drive queue */
  413.     result = AddDriveToQueue (driverGlobals.ramSize / 512, drvrRefNum, &driveNum);
  414.     if (result != noErr)
  415.     {
  416.         Panic("\pAddMyDrive returned negative driveNum!");
  417.         goto Done;
  418.     }
  419.     /* driveNum now = drive number */
  420.     
  421.     /*    Save driveNum in our globals so driver code can verify drive number in
  422.         Prime, Status and Control calls (if need be). The driver also checks 
  423.         driveNum in the driver globals for a non-zero value before accepting
  424.         regular prime, control and status calls.
  425.     */
  426.     driverGlobals.driveNumber = driveNum;
  427.  
  428.     /* set drivers globals */
  429.     *(Ptr *)csParam = (Ptr)&driverGlobals;
  430.     result = Control(drvrRefNum, setGlobalsCC, (Ptr)csParam);
  431.     if (result != noErr)
  432.     {
  433.         Panic("\pControl returned err");
  434.         goto Done;
  435.     }
  436.     
  437.     /* check to see if it got them */
  438.     result = Status(drvrRefNum, getGlobalsSC, (Ptr)csParam);
  439.     if ((result != noErr) || (driverGlobals.ramSize != *(long *)csParam))
  440.     {
  441.         Panic("\pStatus returned err");
  442.         goto Done;
  443.     }
  444.             
  445.     /* zero & mount */
  446.     result = DIZero(driveNum, driverGlobals.volumeName);
  447.     if (result != noErr)
  448.     {
  449.         Panic("\pDIZero returned err");
  450.         goto Done;
  451.     }
  452.     
  453. Done:
  454.     if (result == noErr)
  455.         ShowInitIcon(rLoadOKIcon,true);    /* draw OK icon and move pen */
  456.     else
  457.     {
  458.         dceHandle = GetDCtlEntry(drvrRefNum);
  459.         if (dceHandle != nil)
  460.             if ((**dceHandle).dCtlFlags & dOpenedMask)
  461.             {
  462.                 /* Driver is open - close it */
  463.                 result = CloseDriver(drvrRefNum);
  464.                 if (result == noErr)
  465.                     /* If driver was closed, ramDisk memory was released! */
  466.                     driverGlobals.ramDisk = nil;
  467.             }
  468.         
  469.         if (driveNum != 0)
  470.         {
  471.             result = RemoveDriveFromQueue(driveNum, &driveQElPtr);    /* ignore errors */
  472.             if (result == noErr)
  473.                 /* Dispose of the DrvQEl. Since it was allocated as a
  474.                     MyDrvQEl record, we have to subract 4 from the address */
  475.                 DisposePtr((Ptr)((Ptr)(driveQElPtr) - 4));
  476.         }
  477.         
  478.         // <1.4>
  479.         if (driverInstalled) {
  480.             (void) TradRemoveDriver(drvrRefNum, false);
  481.         }
  482.         
  483.         if (driverGlobals.ramDisk != nil)
  484.             DisposePtr(driverGlobals.ramDisk);
  485.             
  486.         #if        __DebugVersion
  487.             /* ••• Need to add routine to remove TMON/MacsBug debugging macros */
  488.         #endif    __DebugVersion
  489.             
  490.         ShowInitIcon(rLoadBadIcon,true);            /* draw bad load icon and move pen */
  491.     }
  492.     #ifdef THINK_C
  493.         RestoreA4();
  494.     #endif
  495.     #ifdef __MWERKS__
  496.         SetA4(oldA4);
  497.     #endif
  498. }
  499.